﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using GeneralLibs;
using Lists;
using System.Data.SqlClient;
using DevExpress.XtraReports.UI;

namespace ReceivingDelivering.Delivering
{
    public partial class FrmEditDelivering : BasicForms.FrmEditChungTu
    {
        Lists.DeliveringBill _vouchers;
        public FrmEditDelivering()
        {
            InitializeComponent();
            this.Load += new EventHandler(FrmEditDelivering_Load);
        }

        public FrmEditDelivering(Lists.DeliveringBill delivering)
        {
            InitializeComponent();
            _vouchers = delivering;
            this.Load += new EventHandler(FrmEditDelivering_Load);
        }

        void FrmEditDelivering_Load(object sender, EventArgs e)
        {
            #region LookUp Item
            rProduct.DataSource = rUnit.DataSource = rUnitPrice.DataSource = DB.Products.ToList();
            #endregion
            #region Combobox
            WarehouseKeeperIDLookUpEdit.Properties.DataSource = DB.Staffs.Where(p => p.Position.PositionNo == "THUKHO");
            StaffIDLookUpEdit.Properties.DataSource = DB.Staffs.Where(p=>p.Position.PositionNo == "NHANVIEN");
            AccountantIDLookUpEdit.Properties.DataSource = DB.Staffs.Where(p => p.Position.PositionNo == "KETOANTRUONG");
            ProjectIDLookUpEdit.Properties.DataSource = DB.Projects.ToList();
            #endregion
            if (_vouchers == null)
            {
                _EditState = EditState.CreatingNew;
                bindingSource.AddNew();
                this.Text = "New vouchers";
                //Lấy vào số hiệu chứng từ mặc định
                Lists.DeliveringBill objNewvoucher = DB.DeliveringBills.OrderByDescending(p => p.DeleveringNo).FirstOrDefault();
                if (objNewvoucher == null)
                {
                    ((Lists.DeliveringBill)bindingSource.Current).DeleveringNo = "XK0001";
                }
                else
                {
                    string temp = "000" + (int.Parse(objNewvoucher.DeleveringNo.Substring(2)) + 1);
                    ((Lists.DeliveringBill)bindingSource.Current).DeleveringNo = "XK" + temp.Substring(temp.Length - 4);
                }
                ((Lists.DeliveringBill)bindingSource.Current).CreateDate = DateTime.Now;
                ((Lists.DeliveringBill)bindingSource.Current).DeliveringDate = DateTime.Now;
            }
            else
            {
                _EditState = EditState.SavedButNotInLedger;
                bindingSource.Add(DB.DeliveringBills.FirstOrDefault(p => p.DeleveringNo == _vouchers.DeleveringNo));
                this.Text = "Edit vouchers";
            }

            //Bindata for voucher info
            string query = "SELECT di.DeleveringBillID DeleveringID, di.ProductID, p.ProductName , p.Unit, \n" +
                            "        p.DeliveringPrice UnitPrice, di.WarehouseID,  \n" +
                            "        di.DeleveringQuantity Quantity, di.DeleveringQuantity * p.DeliveringPrice ToMoney \n" +
                            "FROM DeliveringBillInfo di INNER JOIN Product p ON p.ProductID = di.ProductID \n" +
                            "WHERE di.DeleveringBillID = @DeleveringID";
            gridObject.DataSource = new DataAccess().ExecuteSelect(query, new SqlParameter("@DeleveringID", (_vouchers == null) ? (object)DBNull.Value : _vouchers.DeleveringID));
            ((DataTable)gridObject.DataSource).ColumnChanged += new DataColumnChangeEventHandler(FrmEditDelivering_ColumnChanged);
            CreateDateDateEdit.Properties.MinValue = DeliveringDateDateEdit.Properties.MinValue = System.Data.SqlTypes.SqlDateTime.MinValue.Value;
            gridViewObject.KeyUp += new KeyEventHandler(gridViewObject_KeyUp);
            
            SetEditState(_EditState);
            CreateDateDateEdit.EditValueChanged += new EventHandler(CreateDateDateEdit_EditValueChanged);
        }

        protected override void SetEditState(EditState editState)
        {
            base.SetEditState(editState);
            switch (editState)
            {
                case EditState.SavedButNotInLedger:
                    gridViewObject.OptionsBehavior.Editable = false;
                    break;
                case EditState.CreatingNew:
                    gridViewObject.OptionsBehavior.Editable = true;
                    break;
                case EditState.Modifying:
                    gridViewObject.OptionsBehavior.Editable = true;
                    break;
            }
        }

        void FrmEditDelivering_ColumnChanged(object sender, DataColumnChangeEventArgs e)
        {
            switch (e.Column.ColumnName)
            {
                case "ProductID":
                    e.Row["UnitPrice"] = DB.Products.FirstOrDefault(p =>p.ProductID.Equals(e.Row["ProductID"])).DeliveringPrice;
                    break;
                case "UnitPrice":
                case "Quantity":
                    e.Row["ToMoney"] = (e.Row.IsNull("UnitPrice") ? (decimal)0 : (decimal)e.Row["UnitPrice"]) * (e.Row.IsNull("Quantity") ? (decimal)0 : (decimal)e.Row["Quantity"]);
                    break;
            }
        }

        protected override bool CheckFullInfo()
        {
            Lists.DeliveringBill delivering = (Lists.DeliveringBill)bindingSource.Current;
            if (string.IsNullOrEmpty(delivering.DeleveringNo))
                throw new Exception("Delivering no not allow null!");
            if(delivering.CreateDate == null)
                throw new Exception("Create date not allow null!");
            if (delivering.DeliveringDate == null)
                throw new Exception("Delivering date not allow null!");
            if(delivering.StaffID == null)
                throw new Exception("Staff not allow null!");
            if (delivering.WarehouseKeeperID == null)
                throw new Exception("WarehouseKeeper not allow null!");
            if (delivering.ProjectID == null)
                throw new Exception("Project not allow null!");
            if (delivering.AccountantID == null)
                throw new Exception("Accountant not allow null!");
            if(gridViewObject.RowCount == 1)
                throw new Exception("Voucher must contain at least one item!");
            if (DB.DeliveringBills.Any(p => p.DeleveringNo == delivering.DeleveringNo && p.DeleveringID != delivering.DeleveringID))
                throw new Exception("Delivering No already exists!");
            System.Collections.Hashtable htContainer = new System.Collections.Hashtable();
            foreach (DataRow row in ((DataTable)gridObject.DataSource).Rows)
            {
                if (row.RowState != DataRowState.Deleted)
                {
                    if (row.IsNull("ProductID"))
                    {
                        throw new Exception("Product not allow null!");
                    }
                    else
                    {
                        if (!htContainer.Contains(row["ProductID"])) htContainer.Add(row["ProductID"], 0);
                        else throw new Exception("Product allready in onther info!");
                    }
                    if (row.IsNull("Quantity"))
                        throw new Exception("Quantity not allow null!");
                }
            }
            if (!CheckNegativeDelivering())
                throw new Exception("Not allow delivering negative product!");
            return true;
        }

        //Check xuất âm
        private bool CheckNegativeDelivering()
        {
            if (_EditState == EditState.CreatingNew)
            {
                DataTable dtSouce = (DataTable)gridObject.DataSource;
                foreach (DataRow row in dtSouce.Rows)
                {
                    if (row.RowState != DataRowState.Deleted)
                    {
                        Product product = DB.Products.FirstOrDefault(p => p.ProductID == (int)row["ProductID"]);
                        if (product != null)
                        {
                            decimal instock = product.InStockQuantity ?? 0;
                            decimal quantity = (row.IsNull("Quantity") ? (decimal)0 : (decimal)row["Quantity"]);
                            if (instock < quantity) return false;
                        }
                    }
                }
            }
            else
            {
                var deliveringInfo = DB.DeliveringBillInfos.Where(p => p.DeleveringBillID == (bindingSource.Current as Lists.DeliveringBill).DeleveringID);
                if (deliveringInfo != null)
                {
                    DataTable dtSouce = (DataTable)gridObject.DataSource;
                    foreach (DataRow row in dtSouce.Rows)
                    {
                        if (row.RowState != DataRowState.Deleted)
                        {
                            decimal newQuantity = (row.IsNull("Quantity") ? (decimal)0 : (decimal)row["Quantity"]);
                            decimal oldQuantity = 0;
                            DeliveringBillInfo oldInfo = deliveringInfo.FirstOrDefault(p => p.ProductID == (int)row["ProductID"]);
                            if (oldInfo != null)
                                oldQuantity = oldInfo.DeleveringQuantity ?? 0;
                            decimal realQuantity = newQuantity - oldQuantity;
                            Product product = DB.Products.FirstOrDefault(p => p.ProductID == (int)row["ProductID"]);
                            if (product != null)
                            {
                                decimal instock = product.InStockQuantity ?? 0;
                                if (instock < realQuantity)
                                {
                                    return false;
                                }
                            }
                        }
                    }
                }
            }
            return true;
        }
        protected override void Save()
        {
            Lists.DeliveringBill delivering = (Lists.DeliveringBill)bindingSource.Current;
            if (_EditState == EditState.CreatingNew)
            {
                DB.DeliveringBills.InsertOnSubmit(delivering);
            }
            DB.DeliveringBillInfos.DeleteAllOnSubmit(DB.DeliveringBillInfos.Where(p => p.DeliveringBill == delivering));
            DataTable dtSouce = (DataTable)gridObject.DataSource;
            foreach (DataRow row in dtSouce.Rows)
            {
                if (row.RowState != DataRowState.Deleted)
                {
                    Lists.DeliveringBillInfo objDelivering = new Lists.DeliveringBillInfo();
                    objDelivering.DeliveringBill = delivering;
                    objDelivering.ProductID = (int)row["ProductID"];
                    objDelivering.WarehouseID = row.IsNull("WarehouseID") ? null : (string)row["WarehouseID"];
                    objDelivering.DeleveringQuantity = row.IsNull("Quantity") ? (decimal)0 : (decimal)row["Quantity"];
                    DB.DeliveringBillInfos.InsertOnSubmit(objDelivering);
                }
            }
            DB.SubmitChanges();
            SetEditState(EditState.SavedButNotInLedger);
        }

        void gridViewObject_KeyUp(object sender, KeyEventArgs e)
        {
            if (_EditState == EditState.SavedButNotInLedger) return;
            if (e.KeyCode == Keys.Delete)
            {
                gridViewObject.DeleteSelectedRows();
            }
        }

        protected override void Print()
        {
            Report rpt = new Report((Lists.DeliveringBill)bindingSource.Current);
            rpt.ShowPreview();
        }

        void CreateDateDateEdit_EditValueChanged(object sender, EventArgs e)
        {
            try
            {
                ((Lists.DeliveringBill)bindingSource.Current).CreateDate = CreateDateDateEdit.DateTime;
                ((Lists.DeliveringBill)bindingSource.Current).DeliveringDate = CreateDateDateEdit.DateTime;
            }
            catch { }
        }
    }
}
